﻿
Imports System.Net.Sockets
Imports System.Runtime.CompilerServices
Imports osi.root.connector
Imports osi.root.utils
Imports osi.root.procedure
Imports osi.root.formation
Imports osi.service.convertor

'public for test, but should not be called out of tcp project
Public Module _talk
    'public for test only
    Public Function prepare_preamble(ByVal sd() As Byte) As Byte()
        Return to_chunk(sd)
    End Function

    'public for test only
    Public Function verify_preamble(ByVal p() As Byte, ByRef len As Int32) As Boolean
        Return parse_as_preamble(p, len)
    End Function

    <Extension()> Public Function package_send(ByVal client As TcpClient,
                                               ByVal buff() As Byte,
                                               ByVal rate_sec As Int32) As event_comb
        Dim ec As event_comb = Nothing
        Return New event_comb(Function() As Boolean
                                  If isemptyarray(buff) Then
                                      Return False
                                  Else
                                      ec = send(client, prepare_preamble(buff), rate_sec)
                                      Return waitfor(ec) AndAlso
                                             goto_next()
                                  End If
                              End Function,
                              Function() As Boolean
                                  If ec.end_result() Then
                                      Return goto_end()
                                  Else
                                      raise_error("failed to send package to ",
                                                  identity(client))
                                      shutdown(client)
                                      Return False
                                  End If
                              End Function)
    End Function

    <Extension()> Public Function package_send(ByVal client As TcpClient,
                                               ByVal p As powerpoint,
                                               ByVal buff() As Byte) As event_comb
        assert(Not p Is Nothing)
        Dim ec As event_comb = Nothing
        Return New event_comb(Function() As Boolean
                                  buff = p.zip_and_encrypt(buff)
                                  ec = package_send(client, buff, p.send_rate_sec)
                                  Return waitfor(ec) AndAlso
                                         goto_next()
                              End Function,
                              Function() As Boolean
                                  Return ec.end_result() AndAlso
                                         goto_end()
                              End Function)
    End Function

    <Extension()> Public Function package_receive(ByVal client As TcpClient,
                                                  ByVal result As pointer(Of Byte()),
                                                  ByVal response_timeout_ms As Int64,
                                                  ByVal rate_sec As Int32) As event_comb
        Dim ec As event_comb = Nothing
        Dim read_len As pointer(Of Int32) = Nothing
        Dim exp_len As Int32 = 0
        Dim r() As Byte = Nothing
        Return New event_comb(Function() As Boolean
                                  ReDim r(preamble_length - 1)
                                  read_len = New pointer(Of Int32)()
                                  ec = receive(client, r, response_timeout_ms, rate_sec, read_len)
                                  Return waitfor(ec) AndAlso
                                         goto_next()
                              End Function,
                              Function() As Boolean
                                  If ec.end_result() AndAlso
                                     (+read_len) = preamble_length AndAlso
                                     verify_preamble(r, exp_len) Then
                                      read_len.set(0)
                                      ReDim r(exp_len - 1)
                                      ec = receive(client, r, 0, rate_sec, read_len)
                                      Return waitfor(ec) AndAlso
                                             goto_next()
                                  Else
                                      raise_error("failed to receive preamble from ",
                                                  identity(client))
                                      shutdown(client)
                                      Return False
                                  End If
                              End Function,
                              Function() As Boolean
                                  If ec.end_result() AndAlso
                                     (+read_len) = exp_len AndAlso
                                     eva(result, r) AndAlso
                                     goto_end() Then
                                      Return goto_end()
                                  Else
                                      raise_error("failed to receive data body from ",
                                                  identity(client))
                                      shutdown(client)
                                      Return False
                                  End If
                              End Function)
    End Function

    <Extension()> Public Function package_receive(ByVal client As TcpClient,
                                                  ByVal p As powerpoint,
                                                  ByVal result As pointer(Of Byte())) As event_comb
        assert(Not p Is Nothing)
        Dim ec As event_comb = Nothing
        Return New event_comb(Function() As Boolean
                                  result.renew()
                                  ec = package_receive(client, result, p.response_timeout_ms, p.receive_rate_sec)
                                  Return waitfor(ec) AndAlso
                                         goto_next()
                              End Function,
                              Function() As Boolean
                                  Return ec.end_result() AndAlso
                                         eva(result, p.unzip_and_decrypt(+result)) AndAlso
                                         goto_end()
                              End Function)
    End Function
End Module
